package com.etong.frame.directive.service.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.etong.frame.directive.Directive;
import com.etong.frame.directive.GroupConfig;
import com.etong.frame.directive.GroupDirective;
import com.etong.frame.directive.impl.database.DirectiveFactoryImpl;
import com.etong.frame.directive.impl.database.DirectiveLoaderImpl;
import com.etong.frame.directive.impl.database.Statement;
import com.etong.frame.directive.mybatis.DirectiveStatement;
import com.etong.frame.directive.mybatis.DirectiveStatementMapper;
import com.etong.frame.directive.service.DirectiveService;
import com.etong.frame.directive.util.CommonStatus;
import com.etong.frame.dispatcher.Dispatcher;
import com.etong.framework.service.JSONRequest;
import com.etong.framework.service.JSONResponse;
import com.etong.framework.service.impl.ServiceImpl;

public class DirectiveServiceImpl extends ServiceImpl implements
		DirectiveService {
	private static final Logger logger = LoggerFactory
			.getLogger(DirectiveServiceImpl.class);

	@Autowired
	DirectiveStatementMapper statementMapper;

	DirectiveFactoryImpl directiveFactory;

	Dispatcher dispatcher;

	@PostConstruct
	public void initOnce() {

		dispatcher = new Dispatcher();
		// 检查管理器
		List<Map<String, Object>> checkerMaps = statementMapper
				.getCheckerConfigs();
		dispatcher.loadCheckers(checkerMaps);

		// 指令工厂
		directiveFactory = new DirectiveFactoryImpl();
		directiveFactory.setDirectiveMapper(statementMapper);

		// 指令配置信息
		List<Map<String, Object>> directiveConfigs = statementMapper
				.getDirectiveConfigs();
		// 创建加载器
		DirectiveLoaderImpl directiveLoader = new DirectiveLoaderImpl();
		directiveLoader.setDirectiveConfigs(directiveConfigs);
		directiveLoader.setDirectiveFactory(directiveFactory);

		// 加载指令
		List<GroupConfig> groupConfigs = statementMapper.getGroupConfigs();
		dispatcher.loadDirectives(directiveLoader);
		dispatcher.loadGroups(groupConfigs);
	}

	@Override
	public JSONResponse createDirective(JSONRequest dataJson) {
		logger.info("Create directive:" + dataJson);

		// 新增时先验证一下是否有效
		JSONResponse res = validateDirective(dataJson);
		if (!res.succeed()) {
			logger.error("Valid directive statement error:" + dataJson);
			return res;
		}

		// 检查 指令是否存在
		DirectiveStatement statement = dataJson.to(DirectiveStatement.class);
		if (0 < statementMapper.checkDirectiveConfig(statement.getName())) {
			res.error(CommonStatus.DIRECTIVE_CREATE_EXISTS,
					"Create service exists");
			return res;
		}

		statementMapper.insertSelective(statement);

		// 插入成功后，重新加载
		reloadDirectives();

		GroupDirective group = dispatcher
				.getGroupDirective(statement.getName());
		res.put("statements", group.getStatements());

		return res;
	}

	public static String uppercaseFirst(String name) {
		char[] cs = name.toCharArray();
		cs[0] -= 32;
		return String.valueOf(cs);

	}

	@Override
	public JSONResponse validateDirective(JSONRequest dataJson) {
		logger.info("Validate directive:" + dataJson);

		JSONResponse res = new JSONResponse();
		Statement statement = dataJson.to(Statement.class);
		if (null == statement) {
			res.error(CommonStatus.DIRECTIVE_BUILD_ERROR,
					"Build directive statement null");
			return res;
		}

		Directive directive = directiveFactory.createDirective(statement);
		if (null == directive) {
			res.error(CommonStatus.DIRECTIVE_BUILD_ERROR,
					"Build directive statement error");
			return res;
		}
		return res;
	}

	@Override
	public JSONResponse updateDirective(JSONRequest dataJson) {
		logger.info("Update directive:" + dataJson);
		Integer directiveId = dataJson.getInteger("id");

		JSONResponse res = new JSONResponse();
		if (null != directiveId) {
			res = validateDirective(dataJson);
			if (!res.succeed()) {
				logger.error("Validate directive config error" + dataJson);
				return res;
			}

			DirectiveStatement statement = dataJson
					.to(DirectiveStatement.class);
			statement.setModify_time(getNowTimestamp());
			statementMapper.updateByPrimaryKeySelective(statement);

			reloadDirectives();

			GroupDirective group = dispatcher.getGroupDirective(statement
					.getName());
			res.put("statements", group.getStatements());
		}

		return res;
	}

	@Override
	public JSONResponse reloadDirectives() {
		initOnce();
		return getAllDirectives();
	}

	@Override
	public JSONResponse removeDirective(JSONRequest dataJson) {
		Integer directiveId = dataJson.getInteger("id");

		if (null != directiveId) {
			DirectiveStatement statement = new DirectiveStatement();
			statement.setId(directiveId);
			statement.setDeleted(true);
			statementMapper.updateByPrimaryKeySelective(statement);
		}
		reloadDirectives();
		return new JSONResponse();
	}

	@Override
	public JSONResponse dispatchDirective(JSONRequest dataJson) {
		return dispatcher.dispatch(dataJson);
	}

	@Override
	public JSONResponse getAllDirectives() {
		logger.info("Get all directives");
		JSONRequest dataJson = new JSONRequest();
		dataJson.put("directive", "getAllDirectives");
		return dispatcher.dispatch(dataJson);
	}
}
